import pathlib
import time
import re
import typing
import os
import yaml
import ctypes
import psutil
import subprocess
import requests
import winsound
import datetime
from selenium.webdriver.edge.webdriver import WebDriver
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
from selenium.common.exceptions import *


def find_element_near_text_v1(
    driver: WebDriver,
    text: str,
    target_element: str,
    target_attributes: typing.Dict[str, str] = None,
    search_radius: typing.Literal["siblings",
                                  "parent", "ancestors"] = "siblings",
    max_distance: int = 3,
    text_match: typing.Literal["exact", "contains"] = "exact"
) -> typing.Optional[WebElement]:
    """
    在指定文本附近查找目标元素

    Args:
        driver: WebDriver 实例
        text: 要查找的文本内容
        target_element: 目标元素标签名 (如 'input', 'button', 'div')
        target_attributes: 目标元素的属性条件
        search_radius: 搜索范围 ('siblings': 兄弟元素, 'parent': 父元素内, 'ancestors': 祖先元素内)
        max_distance: 最大搜索距离 (对于siblings表示最多查找几个兄弟，对于parent/ancestors表示向上查找的层级)
        text_match: 文本匹配方式 ('exact': 精确匹配, 'contains': 包含匹配)

    Returns:
        找到的 WebElement 或 None
    """
    if target_attributes is None:
        target_attributes = {}

    # 查找包含指定文本的元素
    if text_match == "exact":
        text_xpath = f"//*[text()='{text}']"
    else:
        text_xpath = f"//*[contains(text(), '{text}')]"

    text_elements = driver.find_elements(By.XPATH, text_xpath)

    if not text_elements:
        print(f"警告: 未找到包含文本 '{text}' 的元素")
        return None

    # 构建目标元素的XPath条件
    conditions = []
    for attr, value in target_attributes.items():
        conditions.append(f"@{attr}='{value}'")
    target_condition = " and ".join(conditions)
    target_xpath = target_element + \
        (f"[{target_condition}]" if target_condition else "")

    # 遍历所有找到的文本元素，查找附近的目标元素
    candidates = []
    for text_element in text_elements:
        try:
            if search_radius == "siblings":
                # 查找兄弟元素
                for distance in range(1, max_distance + 1):
                    # 查找后续兄弟
                    following_xpath = f"./following-sibling::*[position()<={distance}]/{target_xpath}"
                    following_elements = text_element.find_elements(
                        By.XPATH, following_xpath)

                    # 查找前驱兄弟
                    preceding_xpath = f"./preceding-sibling::*[position()<={distance}]/{target_xpath}"
                    preceding_elements = text_element.find_elements(
                        By.XPATH, preceding_xpath)

                    if following_elements:
                        candidates.append((following_elements[0], distance))
                    if preceding_elements:
                        candidates.append((preceding_elements[0], distance))

                    if following_elements or preceding_elements:
                        break

            elif search_radius in ["parent", "ancestors"]:
                current_element = text_element
                for depth in range(1, max_distance + 1):
                    # 向上查找父级或祖先
                    if search_radius == "parent" and depth > 1:
                        break

                    parent = current_element.find_element(
                        By.XPATH, "./parent::*")
                    elements_in_parent = parent.find_elements(
                        By.XPATH, f".//{target_xpath}")

                    if elements_in_parent:
                        # 计算元素在父级中的位置距离
                        all_children = parent.find_elements(By.XPATH, "./*")
                        text_index = all_children.index(
                            text_element) if text_element in all_children else -1

                        for element in elements_in_parent:
                            if element in all_children:
                                element_index = all_children.index(element)
                                distance = abs(element_index - text_index)
                                candidates.append((element, distance))

                    if search_radius == "ancestors":
                        current_element = parent
                    else:
                        break
        except Exception as e:
            print(f"查找过程中出错: {str(e)}")
            continue

    # 如果没有找到候选元素
    if not candidates:
        print(f"警告: 在文本 '{text}' 附近未找到目标元素")
        return None

    # 选择距离最近的目标元素
    best_candidate = min(candidates, key=lambda x: x[1])
    return best_candidate[0]
